package projectx.web.base;

import game.web.base.LoginUserTrx;
import game.web.base.User;
import game.web.dao.dto.UserDTO;
import game.web.entity.UserEntityManager;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import projectx.core.base.ProjectXException;
import projectx.core.base.ProjectXMessage;
import projectx.core.base.ProjectXProperties;
import projectx.core.base.ProjectXSystemException;
import projectx.core.base.ProjectXUnexpectedException;
import projectx.core.base.ProjectXUserException;
import projectx.core.base.TransactionInterruptException;
import projectx.db.DbUtil;
import projectx.util.ClassUtil;
import projectx.web.base.navi.Function;
import projectx.web.util.ServiceTimeChecker;

public abstract class ProjectXSecurityAction extends Action {

	// --------------------------------------------------------------------------
	// S T A T I C M E M B E R S
	//
	// --------------------------------------------------------------------------

	protected static final int requestMaxCount = ProjectXProperties
			.getPropertyInt("request.max.record", 1000);

	protected static final int sessionMaxCount = ProjectXProperties
			.getPropertyInt("session.max.record", 100);

	protected static final int arvRequestMaxCount = ProjectXProperties
			.getPropertyInt("arv.request.max.record", 200);

	protected static final String forwardSuccess = "success";
	protected static final String forwardFailure = "failure";
	protected static final String forwardLogin = "login";
	protected static final String forwardPrevious = "previous";
	protected static final String forwardJson = "json";

	// --------------------------------------------------------------------------
	// M E M B E R S
	//
	// --------------------------------------------------------------------------
	protected final Logger _log = Logger.getLogger(getClass().getName());

	private final ServiceTimeChecker _timeChecker = new ServiceTimeChecker();

	private UserContext uc;
	private String jsonString = "";

	// --------------------------------------------------------------------------
	// A B S T R A C T M E T H O D S
	//
	// --------------------------------------------------------------------------

	protected abstract boolean isPostMethodOnly();

	protected abstract ActionForward execute(User user, Function function,
			ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpSession session, HttpServletResponse response) throws Exception;

	// --------------------------------------------------------------------------
	// M E T H O D S
	//
	// --------------------------------------------------------------------------
	protected boolean requireFunctionInSession() {
		return true;
	}

	public final ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		System.err.println("ProjectXAction start...");
		//String userId = ProjectXForm.getUserId(request);
		String userId ="USR11331310312050205010859109910";
		try {
			_timeChecker.check();
			if (isPostMethodOnly())
				checkPostMethod(request);

			HttpSession session = request.getSession();

			Function function = getFunction(form, session);

			session.setAttribute("keep.function", function);

			System.err.println("getUser start userid="+userId);

			//获得用户信息
			User user = getUser(userId, session);
			
			System.err.println("getUser end userid="+userId);

			// Check 权限
			// checkUserPrivilege(user, function);

			initUserContext(user,request,session);

			return execute(user, function, mapping, form, request, session,
					response);
		} catch (Throwable e) {
			return exceptionForward(userId, e, mapping, request, response);
		}
	}

	protected Object getAttribute(HttpSession session, String key)
			throws IncorrectAccessException {

		if (session == null) {
			throw new IncorrectAccessException(new ProjectXMessage("E0307"));
		}

		Object ret = session.getAttribute(key);
		if (ret == null) {
			throw new IncorrectAccessException(new ProjectXMessage("E0308", key));
		}

		return ret;
	}

	protected void cleanupSession(HttpServletRequest request,
			HttpSession session, boolean saveToken) {

		if (saveToken) {
			saveToken(request);
		}

		if (session == null) {
			return;
		}

		Enumeration _enum = session.getAttributeNames();
		List list = new ArrayList();

		while (_enum.hasMoreElements()) {

			String attrName = (String) _enum.nextElement();

			if (attrName.startsWith("org.apache.")
					|| attrName.startsWith("keep")) {
				// ignore
			} else {
				list.add(attrName);
			}
		}

		for (int i = 0; i < list.size(); i++) {
			session.removeAttribute((String) list.get(i));
		}
	}

	protected void cleanupSession(HttpServletRequest request,
			HttpSession session) {

		cleanupSession(request, session, true);
	}

	protected ActionForward findForward(ActionMapping mapping,
			String forwardName) throws IncorrectAccessException {
		ActionForward next = mapping.findForward(forwardName);

		if (next == null) {
			throw new IncorrectAccessException(new ProjectXMessage("E0303",
					forwardName));
		}

		return next;
	}

	protected void addError(ActionErrors errors, ProjectXMessage message) {

		ProjectXForm.addError(errors, message);
	}

	protected void addError(ActionErrors errors, ProjectXException exception) {

		ProjectXForm.addError(errors, exception);
	}

	protected void saveError(HttpServletRequest request, ProjectXMessage message) {

		ActionErrors errors = new ActionErrors();
		addError(errors, message);
		saveErrors(request, errors);
	}

	protected void saveError(HttpServletRequest request,
			ProjectXException exception) {

		ActionErrors errors = new ActionErrors();
		addError(errors, exception);
		saveErrors(request, errors);
	}

	protected void checkRecordCount(int recordCount, int maxCount,
			HttpServletRequest request, HttpSession session)
			throws ProjectXUserException {
		if (recordCount == 0) {

			throw new ProjectXUserException("W0100");
		}

		session.setAttribute("maxCount", new Integer(maxCount));

		if (recordCount > maxCount) {

			saveError(request, new ProjectXMessage("W0101",
					new Integer(maxCount)));
		}
	}

	protected void saveNoDataMessage(HttpServletRequest request) {

		saveError(request, new ProjectXMessage("W0102"));
	}

	protected void checkToken(HttpServletRequest request)
			throws IncorrectAccessException {

		checkToken(request, true);
	}

	protected void checkToken(HttpServletRequest request, boolean saveToken)
			throws IncorrectAccessException {

		if (!isTokenValid(request)) {
			throw new IncorrectAccessException(new ProjectXMessage("E0310"));
		}
		if (saveToken) {
			saveToken(request);
		}
	}

	protected void logDebug(String userId, Object msg) {
		ProjectXForm.logDebug(_log, userId, msg);
	}

	protected void logInfo(String userId, Object msg) {
		ProjectXForm.logInfo(_log, userId, msg);
	}

	protected void logWarn(String userId, Object msg) {
		ProjectXForm.logWarn(_log, userId, msg);
	}

	protected void logError(String userId, Object msg) {
		ProjectXForm.logError(_log, userId, msg);
	}

	protected void logFatal(String userId, Object msg) {
		ProjectXForm.logFatal(_log, userId, msg);
	}

	protected void logError(String userId, Object msg, Throwable t) {
		ProjectXForm.logError(_log, userId, msg, t);
	}

	protected void logFatal(String userId, Object msg, Throwable t) {
		ProjectXForm.logFatal(_log, userId, msg, t);
	}

	private void checkPostMethod(HttpServletRequest request)
			throws IncorrectAccessException {

		if (!ProjectXForm.isPostMethod(request)) {
			throw new IncorrectAccessException(new ProjectXMessage("E0302"));
		}
	}

	private Function getFunction(ActionForm form, HttpSession session)
			throws IncorrectAccessException {
		ProjectXForm polarisForm = (ProjectXForm) form;
		String funcId = (polarisForm == null) ? null : polarisForm.getFuncId();

		Function function = getFunction(session);

		return function;
	}

	private Function getFunction(HttpSession session) {

		return (Function) session.getAttribute("keep.function");
	}

	private User getUser(String userId, HttpSession session)
			throws ProjectXUserException, ProjectXSystemException {

		User user = (User) session.getAttribute("keep.user");

		
		if (user == null) {
			user = LoginUserTrx.execute(userId);
			session.setAttribute("keep.user", user);
			logInfo(userId, "Login");
		}
		else
		{
			user = LoginUserTrx.execute(user.getUserid());
			System.err.println("ProjectXAction--->user.Contactno="+user.getContactno());
			session.setAttribute("keep.user", user);
			logInfo(userId, "Login");
		}

		return user;
	}

	private ActionForward exceptionForward(String userId, Throwable e,
			ActionMapping mapping, HttpServletRequest request,
			HttpServletResponse response) {
		if (response.isCommitted()) {
			return null;
		}

		ProjectXException ex = null;

		if (e instanceof TransactionInterruptException) {

			ex = (ProjectXException) e;

			if (ex instanceof ProjectXUserException) {
				logWarn(userId, ex);
			} else {
				logError(userId, ex, e);
			}

			cleanupSession(request, request.getSession(false));
		} else if (e instanceof ProjectXUserException) {

			logWarn(userId, e);

			if (ProjectXForm.isPostMethod(request)) {

				saveError(request, (ProjectXUserException) e);
				return mapping.getInputForward();
			}
		} else {
			ex = new ProjectXUnexpectedException(e);
			logFatal(userId, e, e);

			cleanupSession(request, request.getSession(false));
		}

		request.setAttribute("exception", e);

		// return mapping.findForward("error");
		return errorPageFoward(mapping);
	}

	public void initUserContext(User user,HttpServletRequest request, HttpSession session) {
		uc = (UserContext) session.getAttribute(ConstantsProjectX.USER_CONTEXT);
		if (uc == null) {
			uc = new UserContext();
		}

		if (!uc.containsKey(ConstantsProjectX.USER_ID)) {
			uc.put(ConstantsProjectX.CURRENT_USER, user);
			uc.put(ConstantsProjectX.USER_ID, user.getUserid());
			uc.put(ConstantsProjectX.CURRENT_IP, getIpAddr(request));
		}
		System.err.println("initUserContext userid="+user.getUserid());
	}
	
	public String getIpAddr(HttpServletRequest request) {    
	    String ip = request.getHeader("x-forwarded-for");    
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
    	          ip = request.getHeader("Proxy-Client-IP");    
    	  	      }    
	      if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
	  	          ip = request.getHeader("WL-Proxy-Client-IP");    
	   }    
		   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
		    ip = request.getRemoteAddr();    
		   }    
	   return ip;    
		}  

	public String getRemortIP(HttpServletRequest request) {    
		   if (request.getHeader("x-forwarded-for") == null) {    
		       return request.getRemoteAddr();    
		    }    
		   return request.getHeader("x-forwarded-for");    
	}   


	public UserContext getUc() {
		return uc;
	}

	protected Object getUcAttribute(Object key) {
		return uc.get(key);
	}

	protected void setUcAttribute(Object key, Object value) {
		uc.put(key, value);
	}

	protected void removeUcAttribute(Object key) {
		uc.remove(key);
	}

	protected ActionForward errorPageFoward(ActionMapping mapping) {
		return mapping.findForward("error");
	}

	protected String getUserId() {
		return getUserId(false);
	}

	protected String getUserId(boolean isFull) {
		String userId = (String) getUcAttribute(ConstantsProjectX.USER_ID);
		if (isFull) {
			return userId;
		} else {
			return DbUtil.chopId(userId);
		}

	}

	public String getJsonString() {
		return jsonString;
	}

	public void setJsonString(String jsonString) {
		this.jsonString = jsonString;
	}


	protected void saveErrors(HttpServletRequest request, List errList) {

		ActionErrors errors = new ActionErrors();
		if (errList != null) {

			Iterator it = errList.iterator();

			while (it.hasNext()) {
				Object errObj = it.next();
				if (errObj instanceof ProjectXMessage) {
					ProjectXMessage errMsg = (ProjectXMessage) errObj;
					addError(errors, errMsg);
				}
			}
			saveErrors(request, errors);
		}
	}

	protected void debugBegin() {
		_log.debug(ClassUtil.getClassName(this) + " execute begin.");
	}

	protected void debugEnd() {
		_log.debug(ClassUtil.getClassName(this) + " execute end.");
	}
}
